package com.shop.loan.service.impl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.shop.loan.mapper.UserByMybatisMapper;
import com.shop.loan.mapper.UserReportByMybatisMapper;
import com.shop.loan.model.common.Code;
import com.shop.loan.model.common.ResResult;
import com.shop.loan.model.entity.SettingByMybatis;
import com.shop.loan.model.entity.UserByMybatis;
import com.shop.loan.model.entity.UserReportByMybatis;
import com.shop.loan.model.enums.ReportType;
import com.shop.loan.model.vo.UserReportVo;
import com.shop.loan.redis.RedisCache;
import com.shop.loan.redis.RedisLockUtil;
import com.shop.loan.redis.RedisUtil;
import com.shop.loan.rentaldata.RentalDataUtil;
import com.shop.loan.service.MachineRuleService;
import com.shop.loan.service.SettingService;
import com.shop.loan.service.UserReportService;
import com.shop.loan.util.Util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.util.Date;
import java.util.UUID;

@Slf4j
@Service
public class UserReportServiceImpl implements UserReportService {

    @Resource
    RentalDataUtil rentalDataUtil;

    @Resource
    SettingService settingService;

    @Resource
    RedisLockUtil redisLockUtil;

    @Resource
    RedisUtil redisUtil;

    @Lazy
    @Resource
    MachineRuleService machineRuleService;

    @Resource
    UserReportByMybatisMapper userReportByMybatisMapper;

    @Resource
    UserByMybatisMapper userByMybatisMapper;


    @Transactional
    @Override
    public ResResult getUserReport(UserReportVo userReportVo, boolean updateMachine) {
        if (userReportVo.getUserId() == null || userReportVo.getType() == null) {
            return new ResResult(Code.PARAM_LACK);
        }
        userReportVo.setGetNew(userReportVo.getGetNew() == null ? 0 : userReportVo.getGetNew());

        Jedis jedis = redisUtil.getJedis();
        String lockKey = RedisCache.reportLock + userReportVo.getUserId() + "_" + userReportVo.getType();
        String lockValue = UUID.randomUUID().toString();
        try {
            if (!redisLockUtil.lock(jedis, lockKey, lockValue)) {
                return new ResResult(Code.REPORT_WAIT);
            }
            log.info("开始获取报告:{}", lockKey);
            UserByMybatis user = userByMybatisMapper.selectByPrimaryKey(userReportVo.getUserId());
            if (!StringUtils.hasText(user.getCardNum())) {
                return new ResResult(Code.USER_IDENTITY_AUTH_LACK);
            }

            SettingByMybatis setting = settingService.getSetting();
            UserReportByMybatis userReport = userReportByMybatisMapper.selectByUserReport(user.getCardNum(), user.getMobile(), userReportVo.getType());

            if (userReport == null || userReportVo.getGetNew() == 1 || DateUtil.between(userReport.getUpdateTime(), new Date(), DateUnit.DAY) > setting.getReportTime()) {
                //数据库若不存在/时间太久则重新获取报告
                String infoJs = null;
                if (userReportVo.getType() == ReportType.Tlx.getType().intValue()) {
                    infoJs = rentalDataUtil.getTlxInfo(user.getCardName(), user.getMobile(), user.getCardNum());
                } else if (userReportVo.getType() == ReportType.TanZhenC.getType().intValue()) {
                    infoJs = rentalDataUtil.getTanZhenC(user.getCardName(), user.getMobile(), user.getCardNum());
                } else if (userReportVo.getType() == ReportType.LeiDa.getType().intValue()) {
                    infoJs = rentalDataUtil.getRiskLeiDa(user.getCardName(), user.getMobile(), user.getCardNum());
                }
                if (!JSON.isValidObject(infoJs)) {
                    return new ResResult(Code.REPORT_GET_FAIL.getCode(), infoJs, null);
                }
                userReport = new UserReportByMybatis();
                userReport.setCreateTime(new Date());
                userReport.setUpdateTime(new Date());
                userReport.setIdCardName(user.getCardName());
                userReport.setIdCardNumber(user.getCardNum());
                userReport.setMobile(user.getMobile());
                userReport.setInfoJson(infoJs);
                userReport.setType(userReportVo.getType());
//                userReport.setLoanOrderId(userReportVo.getOrderId());
                userReportByMybatisMapper.insertSelective(userReport);
                if (userReportVo.getType() == ReportType.LeiDa.getType().intValue() || userReportVo.getType() == ReportType.TanZhenC.getType().intValue()) {
                    if (updateMachine) {
                        //报告获取成功后 重新生成机审报告
                        machineRuleService.createUpdateMachineReportByASync(userReportVo.getUserId());
                    }
                }
                return new ResResult(Code.SUCCESS, userReport);
            }
            return new ResResult(Code.SUCCESS, userReport);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(Util.GetErrorDetails(e));
        } finally {
            if (jedis != null) {
                redisLockUtil.release(jedis, lockKey, lockValue);
                jedis.close();
            }
        }
        return new ResResult(Code.FAIL);
    }

//    @Override
//    public ResResult postUserReportByAdmin(UserReportVo userReport) {
//        String infoJs = null;
//        if (userReport.getType() == ReportType.Tlx.getType().intValue()) {
//            infoJs = rentalDataUtil.getTlxInfo(userReport.getIdCardName(), userReport.getMobile(), userReport.getIdCardNumber());
//        } else if (userReport.getType() == ReportType.TanZhenC.getType().intValue()) {
//            infoJs = rentalDataUtil.getTanZhenC(userReport.getIdCardName(), userReport.getMobile(), userReport.getIdCardNumber());
//        } else if (userReport.getType() == ReportType.LeiDa.getType().intValue()) {
//            infoJs = rentalDataUtil.getRiskLeiDa(userReport.getIdCardName(), userReport.getMobile(), userReport.getIdCardNumber());
//        }
//        if (!JSON.isValidObject(infoJs)) {
//            return new ResResult(Code.REPORT_GET_FAIL.getCode(), infoJs, null);
//        }
//
//        Long orderId = System.currentTimeMillis();
//        UserReportByMybatis insertUserReport = new UserReportByMybatis();
//        insertUserReport.setCreateTime(new Date());
//        insertUserReport.setIdCardName(userReport.getIdCardName());
//        insertUserReport.setIdCardNumber(userReport.getIdCardNumber());
//        insertUserReport.setMobile(userReport.getMobile());
//        insertUserReport.setInfoJson(infoJs);
//        insertUserReport.setType(userReport.getType());
//        insertUserReport.setLoanOrderId(orderId);
//        userReportByMybatisMapper.insertSelective(insertUserReport);
//        return new ResResult(Code.SUCCESS);
//    }


    /**
     * 管理员查看报告
     * @param userReportVo
     * @param updateMachine
     * @return
     */
    public ResResult getUserReportByAdmin(UserReportVo userReportVo, boolean updateMachine) {
        if (userReportVo.getUserId() == null || userReportVo.getType() == null) {
            return new ResResult(Code.PARAM_LACK);
        }
        userReportVo.setGetNew(userReportVo.getGetNew() == null ? 0 : userReportVo.getGetNew());

        UserByMybatis user = userByMybatisMapper.selectByPrimaryKey(userReportVo.getUserId());
        if (!StringUtils.hasText(user.getCardNum())) {
            return new ResResult(Code.USER_IDENTITY_AUTH_LACK);
        }

        if (userReportVo.getGetNew() == 1) {
            return getUserReport(userReportVo, updateMachine);
        }else{
            UserReportByMybatis userReport = userReportByMybatisMapper.selectByUserReport(user.getCardNum(), user.getMobile(), userReportVo.getType());
            return new ResResult(Code.SUCCESS, userReport);
        }
    }


//    @Override
//    public String getReportSearchId(Long userOrderId) {
//        UserReport userReport = eruptDao.queryEntity(UserReport.class,
//                " type = :type and uses_order_id = :userOrderId",
//                new HashMap<String, Object>(1) {{
//                    this.put("type", 2);
//                    this.put("userOrderId", userOrderId);
//                }});
//        if (userReport != null) {
//            return userReport.getSearchOrderId();
//        }
//        return null;
//    }
}
